﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;
using ICSharpCode.AvalonEdit;

namespace Poet.Views
{
    /// <summary>
    /// Interaction logic for SplitTextEditorView.xaml
    /// </summary>
    public partial class SplitableTextEditorView
    {

        public Action<TextEditor> OnTextEditorChanged = te => { };

        public static readonly DependencyProperty IsSplitedProperty =
            DependencyProperty.Register("IsSplited", typeof (bool), typeof (SplitableTextEditorView),
                                        new PropertyMetadata(OnSplitChanged));

        private static readonly GridLengthConverter GridLengthConverter = new GridLengthConverter();

        private GridLength _row0Height;

        private GridLength _row2Height;

        private SplitableTextEditorView _rootSplitableTextEditorView;

        /// <summary>
        /// 
        /// </summary>
        public MouseWheelEventHandler MouseWheelEventHandler = (o, e) => { };

        /// <summary>
        /// 
        /// </summary>
        public TextCompositionEventHandler TextCompositionEventHandler = (o, e) => { };

        public SplitableTextEditorView()
        {
            InitializeComponent();
            _row0Height = Convert(1.0 + "*");
            _row2Height = Convert(1.0 + "*");
            TextEditorView.GotFocus += TextEditorViewOnGotFocus;
            TextEditorView.PreviewMouseWheel += (o, e) => This.GetRoot().MouseWheelEventHandler(o, e);
            TextEditorView.PreviewTextInput += (o, e) => This.GetRoot().TextCompositionEventHandler(o, e);
            TextEditorView.TextArea.DocumentChanged +=
                (o0, e0) =>
                    {
                        if (TextEditorView.TextArea.Document != null)
                            TextEditorView.TextArea.Document.Changed +=
                                (o1, e1) => TextEditorView.TextArea.UpdateFoldings();
                    };
        }

        public bool IsSplited
        {
            get { return (bool) GetValue(IsSplitedProperty); }
            set { SetValue(IsSplitedProperty, value); }
        }

        private static void OnSplitChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
        {
            var @this = (SplitableTextEditorView)dependencyObject;
            if (@this.IsSplited)
            {
                if (@this.ContentView.Content == null)
                {
                    var splitableEditor = new SplitableTextEditorView {_rootSplitableTextEditorView = @this};
                    splitableEditor.TextEditorView.TextArea.Caret.Offset = @this.TextEditorView.TextArea.Caret.Offset;
                    //splitableEditor.TextEditorView.OnApplyTemplate();
                    splitableEditor.TextEditorView.TemplateApplied +=
                        () =>
                        {
                            splitableEditor.TextEditorView.ScrollToVerticalOffset(
                                @this.TextEditorView.VerticalOffset);
                            splitableEditor.TextEditorView.ScrollToHorizontalOffset(
                                @this.TextEditorView.HorizontalOffset);
                        };

                    splitableEditor._rootSplitableTextEditorView = @this;
                    @this.ContentView.Content = splitableEditor;
                }

                @this.Row0.Height = @this._row0Height;
                @this.Row2.Height = @this._row2Height;
                @this.ContentView.Visibility =
                    @this.Splitter.Visibility =
                    Visibility.Visible;
            }
            else
            {
                @this.ContentView.Visibility =
                    @this.Splitter.Visibility =
                    Visibility.Collapsed;
                @this._row0Height = @this.Row0.Height;
                @this._row2Height = @this.Row2.Height;
                @this.Row2.Height = Convert(0.0 + "*");
            }

            @this.TextEditorView.Focus();
        }


        private void TextEditorViewOnGotFocus(object sender, RoutedEventArgs routedEventArgs)
        {
            OnTextEditorChanged((TextEditor)sender);
            if (_rootSplitableTextEditorView != null)
                _rootSplitableTextEditorView.TextEditorViewOnGotFocus(sender, routedEventArgs);
            else OnTextEditorChanged((TextEditorView)sender);
        }

        private static GridLength Convert(string sizeString)
        {
            var value = GridLengthConverter.ConvertFrom(sizeString);
            return value == null ? GridLength.Auto : (GridLength) value;
        }

        private SplitableTextEditorView GetRoot()
        {
            return _rootSplitableTextEditorView == null
                       ? this
                       : _rootSplitableTextEditorView.GetRoot();
        }

        private Timer _timer;

        private double _rest;

        private void OnMouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (Keyboard.GetKeyStates(Key.LeftCtrl) == KeyStates.Down ||
                Keyboard.GetKeyStates(Key.RightCtrl) == KeyStates.Down)
                return;

            var scrollViewer = (ScrollViewer) sender;
            if (_timer == null)
            {
                _timer = new Timer {Interval = 1};
                _timer.Tick +=
                    (o, args) =>
                        {
                            if (-1 < _rest && _rest < 1) _timer.Stop();
                            scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - _rest/10);
                            var caretLine = TextEditorView.TextArea.Caret.Line;
                            var hasCaret = TextEditorView.TextArea.TextView.GetVisualLine(caretLine) != null;
                            _rest = hasCaret ? _rest/1.17 : _rest/1.15;
                            //_rest = _rest/1.15;
                            if (_rest*_rest < 5) _rest = 0;
                        };
            }

            _rest = e.Delta*e.Delta*e.Delta/10000.0;
            e.Handled = true;
            _timer.Start();
        }
    }
}
